package jehc.djshi.file.util.office;
import cn.hutool.core.io.IORuntimeException;
import cn.hutool.core.io.IoUtil;
import jehc.djshi.common.util.StringUtil;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.tomcat.util.http.fileupload.IOUtils;
import org.jodconverter.core.DocumentConverter;
import org.jodconverter.core.document.DefaultDocumentFormatRegistry;
import org.jodconverter.core.office.OfficeException;
import org.jodconverter.core.office.OfficeManager;
import org.jodconverter.local.LocalConverter;
import org.jodconverter.local.filter.text.PageMarginsFilter;
import org.jodconverter.local.office.LocalOfficeManager;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.util.ArrayList;
import java.util.List;

/**
 * @Desc Office
 * @Author 邓纯杰
 * @CreateTime 2012-12-12 12:12:12
 */
@Component
@Slf4j
@Data
public class OfficeUtil {

    @Value("${jehc.office.home:}")
    private String officeHome;//LibreOffice 根目录

    @Value("${jehc.office.ports:2002}")
    private String portNumbers;//开启多个LibreOffice进程，每个端口对应一个进程（即每个进程 多个逗号分隔）

    @Value("${jehc.office.maxTasksPerProcess:100}")
    private Integer maxTasksPerProcess;//LibreOffice进程重启前的最大进程数

    @Value("${jehc.office.processTimeout:120000}")
    private Long processTimeout;//一个进程的超时时间 默认120000 毫秒

    @Value("${jehc.office.taskQueueTimeout:30000}")
    private Long taskQueueTimeout;//任务队列的超时时间 默认30000 毫秒

    @Value("${jehc.office.taskExecutionTimeout:120000}")
    private Long taskExecutionTimeout;//任务执行的超时时间 默认120000 毫秒
    /**
     * 定义OfficeManager
     */
    private static OfficeManager officeManager;
//
//    @Resource
//    private OnlineConverter onlineDocumentConverter;
//
//    @Resource
//    private LocalConverter localConverter;

    /**
     *
     */
    public OfficeUtil(){

    }

    /**
     *
     */
    public void initOfficeManager(){
        if(officeManager != null){
            return;
        }
        if(StringUtil.isEmpty(portNumbers)){
            log.warn("未能获取到Office端口配置：{}",portNumbers);
            return;
        }
        if(StringUtil.isEmpty(officeHome)){
            log.warn("未能获取到Office安装路径：{}",officeHome);
            return;
        }
        String[] ports = StringUtils.split(portNumbers, ", ");
        List<Integer> iports = new ArrayList<>();
        for(int i = 0; i < ports.length; i++){
            iports.add(new Integer(ports[i])) ;
        }
        officeManager= LocalOfficeManager.builder().
                officeHome(officeHome).
                portNumbers(iports.stream().mapToInt(Integer::valueOf).toArray()).
                maxTasksPerProcess(maxTasksPerProcess).
                taskExecutionTimeout(taskExecutionTimeout).
                taskQueueTimeout(taskQueueTimeout).
                processTimeout(processTimeout).install().build();
        start();//调用启动
    }

    /**
     *
     */
    public static void start(){
        if(officeManager.isRunning()){
            return;
        }
        try {
            officeManager.start();
        } catch (Exception e) {
            log.error("OfficeManager服务启动失败：{}",e);
        }
    }

    /**
     * 关闭Office
     * @throws OfficeException
     */
    public static void stop() throws OfficeException {
        if(officeManager!=null){
            officeManager.stop();
        }
    }

//    @Bean
//    @ConditionalOnMissingBean
//    @ConditionalOnBean({OfficeManager.class})
//    public DocumentConverter jodConverter() {
//        return LocalConverter.make(officeManager);
//    }

    /**
     * 验证是否图片
     * @param extName
     * @return
     */
    public boolean isImage(String extName) {
        if ("jpg".equalsIgnoreCase(extName))
            return true;
        if ("gif".equalsIgnoreCase(extName))
            return true;
        if ("bmp".equalsIgnoreCase(extName))
            return true;
        if ("jpeg".equalsIgnoreCase(extName))
            return true;
        if ("png".equalsIgnoreCase(extName))
            return true;
        return false;
    }

    /**
     * doc转为pdf
     * @param inPath
     * @param outPath
     */
    public void doc2PDF(String inPath, String outPath) {
        InputStream input = null;
        OutputStream output = null;
        try {
            input = new FileInputStream(inPath);
            output = new FileOutputStream(outPath);
            PageMarginsFilter pageMarginsFilter = new PageMarginsFilter(20, 20, 20, 20);
            LocalConverter.builder().officeManager(officeManager)
                    .filterChain(pageMarginsFilter)
                    .build()
                    .convert(input)
                    .as(DefaultDocumentFormatRegistry.DOCX)
                    .to(output)
                    .as(DefaultDocumentFormatRegistry.PDF).execute();
            output.flush();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                input.close();
                output.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 预览
     * @param multipartFile
     * @param response
     */
    public void preview(MultipartFile multipartFile, HttpServletResponse response) {
        if (multipartFile == null) {
            return;
        }
        InputStream inputStream = null;
        OutputStream outputStream = null;
        try {
            inputStream = multipartFile.getInputStream();
            outputStream = response.getOutputStream();
            String fileName = multipartFile.getOriginalFilename();
            String suffix = null;
            if (fileName.lastIndexOf(".") != -1 && fileName.lastIndexOf(".") != 0) {
                suffix = fileName.substring(fileName.lastIndexOf(".") + 1);
            }
            if("doc".equals(suffix) || "docx".equals(suffix) ||
                    "xls".equals(suffix) || "xlsx".equals(suffix) ||
                    "csv".equals(suffix) || "ppt".equals(suffix) ||
                    "pptx".equals(suffix)){
                if(null == officeManager || !officeManager.isRunning()){
                    log.warn("officeManager未启动，正在重新启动...");
                    initOfficeManager();
                }
                DocumentConverter documentConverter = LocalConverter.make(officeManager);
                documentConverter.convert(inputStream).to(outputStream).as(documentConverter.getFormatRegistry().getFormatByExtension("pdf")).execute();
            } else if("pdf".equals(suffix) || "txt".equals(suffix) ||
                    "xml".equals(suffix) || "md".equals(suffix) ||
                    "json".equals(suffix) || "html".equals(suffix) ||
                    "htm".equals(suffix) || "gif".equals(suffix)||
                    "jpg".equals(suffix) || "jpeg".equals(suffix) ||
                    "png".equals(suffix) || "ico".equals(suffix) ||
                    "bmp".equals(suffix)){
                IoUtil.copy(inputStream, outputStream);
            } else {
                outputStream.write("暂不支持预览此类型附件".getBytes());
            }
        } catch (IORuntimeException e) {
            log.error("附件预览IO运行异常：{}", e.getMessage());
        } catch (IOException e) {
            log.error("附件预览IO异常：{}", e.getMessage());
        } catch (OfficeException e) {
            log.error("附件预览Office异常：{}", e.getMessage());
        } finally {
            IOUtils.closeQuietly(inputStream);
        }
        IoUtil.writeUtf8(outputStream, true);
    }

    /**
     * 预览
     * @param inputStream
     * @param fileName
     * @param response
     */
    public void preview(InputStream inputStream, String fileName, HttpServletResponse response) {
        if (inputStream == null) {
            return;
        }
        OutputStream outputStream = null;
        try {
            outputStream = response.getOutputStream();
            String suffix = null;
            if (fileName.lastIndexOf(".") != -1 && fileName.lastIndexOf(".") != 0) {
                suffix = fileName.substring(fileName.lastIndexOf(".") + 1);
            }
            if("doc".equals(suffix) || "docx".equals(suffix) ||
                    "xls".equals(suffix) || "xlsx".equals(suffix) ||
                    "csv".equals(suffix) || "ppt".equals(suffix) ||
                    "pptx".equals(suffix)){
                if(null == officeManager || !officeManager.isRunning()){
                    log.warn("officeManager未启动，正在重新启动...");
                    initOfficeManager();
                }
                DocumentConverter documentConverter = LocalConverter.make(officeManager);
                documentConverter.convert(inputStream).to(outputStream).as(documentConverter.getFormatRegistry().getFormatByExtension("pdf")).execute();
            } else if("pdf".equals(suffix) || "txt".equals(suffix) ||
                    "xml".equals(suffix) || "md".equals(suffix) ||
                    "json".equals(suffix) || "html".equals(suffix) ||
                    "htm".equals(suffix) || "gif".equals(suffix)||
                    "jpg".equals(suffix) || "jpeg".equals(suffix) ||
                    "png".equals(suffix) || "ico".equals(suffix) ||
                    "bmp".equals(suffix)){
                IoUtil.copy(inputStream, outputStream);
            } else {
                outputStream.write("暂不支持预览此类型附件".getBytes());
            }
        } catch (IORuntimeException e) {
            log.error("附件预览IO运行异常：{}", e.getMessage());
        } catch (IOException e) {
            log.error("附件预览IO异常：{}", e.getMessage());
        } catch (OfficeException e) {
            log.error("附件预览Office异常：{}", e.getMessage());
        } finally {
            IOUtils.closeQuietly(inputStream);
        }
        IoUtil.writeUtf8(outputStream, true);
    }
}
